home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2000 March / maximum-cd-2000-03.iso / Quake3 Game Source / Q3AGameSource.exe / Main / g_arenas.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-01-18  |  8.8 KB  |  317 lines

  1. // Copyright (C) 1999-2000 Id Software, Inc.
  2. //
  3. //
  4. // g_arenas.c
  5. //
  6.  
  7. #include "g_local.h"
  8.  
  9.  
  10. gentity_t    *podium1;
  11. gentity_t    *podium2;
  12. gentity_t    *podium3;
  13.  
  14.  
  15. /*
  16. ==================
  17. UpdateTournamentInfo
  18. ==================
  19. */
  20. void UpdateTournamentInfo( void ) {
  21.     int            i;
  22.     gentity_t    *player;
  23.     int            playerClientNum;
  24.     int            n;
  25.     int            accuracy;
  26.     int            perfect;
  27.     int            msglen;
  28.     int            buflen;
  29.     char        buf[32];
  30.     char        msg[256];
  31.  
  32.     // find the real player
  33.     player = NULL;
  34.     for (i = 0; i < level.maxclients; i++ ) {
  35.         player = &g_entities[i];
  36.         if ( !player->inuse ) {
  37.             continue;
  38.         }
  39.         if ( !( player->r.svFlags & SVF_BOT ) ) {
  40.             break;
  41.         }
  42.     }
  43.     // this should never happen!
  44.     if ( !player || i == level.maxclients ) {
  45.         return;
  46.     }
  47.     playerClientNum = i;
  48.  
  49.     CalculateRanks();
  50.  
  51.     if ( level.clients[playerClientNum].sess.sessionTeam == TEAM_SPECTATOR ) {
  52.         Com_sprintf( msg, sizeof(msg), "postgame %i %i 0 0 0 0 0 0", level.numNonSpectatorClients, playerClientNum );
  53.     }
  54.     else {
  55.         if( player->client->ps.persistant[PERS_ACCURACY_SHOTS] ) {
  56.             accuracy = player->client->ps.persistant[PERS_ACCURACY_HITS] * 100 / player->client->ps.persistant[PERS_ACCURACY_SHOTS];
  57.         }
  58.         else {
  59.             accuracy = 0;
  60.         }
  61.         perfect = ( level.clients[playerClientNum].ps.persistant[PERS_RANK] == 0 && player->client->ps.persistant[PERS_KILLED] == 0 ) ? 1 : 0;
  62.         Com_sprintf( msg, sizeof(msg), "postgame %i %i %i %i %i %i %i %i", level.numNonSpectatorClients, playerClientNum, accuracy,
  63.             player->client->ps.persistant[PERS_IMPRESSIVE_COUNT], player->client->ps.persistant[PERS_EXCELLENT_COUNT],
  64.             player->client->ps.persistant[PERS_GAUNTLET_FRAG_COUNT], player->client->ps.persistant[PERS_SCORE],
  65.             perfect );
  66.     }
  67.  
  68.     msglen = strlen( msg );
  69.     for( i = 0; i < level.numNonSpectatorClients; i++ ) {
  70.         n = level.sortedClients[i];
  71.         Com_sprintf( buf, sizeof(buf), " %i %i %i", n, level.clients[n].ps.persistant[PERS_RANK], level.clients[n].ps.persistant[PERS_SCORE] );
  72.         buflen = strlen( buf );
  73.         if( msglen + buflen + 1 >= sizeof(msg) ) {
  74.             break;
  75.         }
  76.         strcat( msg, buf );
  77.     }
  78.     trap_SendConsoleCommand( EXEC_APPEND, msg );
  79. }
  80.  
  81.  
  82. static gentity_t *SpawnModelOnVictoryPad( gentity_t *pad, vec3_t offset, gentity_t *ent, int place ) {
  83.     gentity_t    *body;
  84.     vec3_t        vec;
  85.     vec3_t        f, r, u;
  86.  
  87.     body = G_Spawn();
  88.     if ( !body ) {
  89.         G_Printf( S_COLOR_RED "ERROR: out of gentities\n" );
  90.         return NULL;
  91.     }
  92.  
  93.     body->classname = ent->client->pers.netname;
  94.     body->client = ent->client;
  95.     body->s = ent->s;
  96.     body->s.eType = ET_PLAYER;        // could be ET_INVISIBLE
  97.     body->s.eFlags = 0;                // clear EF_TALK, etc
  98.     body->s.powerups = 0;            // clear powerups
  99.     body->s.loopSound = 0;            // clear lava burning
  100.     body->s.number = body - g_entities;
  101.     body->timestamp = level.time;
  102.     body->physicsObject = qtrue;
  103.     body->physicsBounce = 0;        // don't bounce
  104.     body->s.event = 0;
  105.     body->s.pos.trType = TR_STATIONARY;
  106.     body->s.groundEntityNum = ENTITYNUM_WORLD;
  107.     body->s.legsAnim = LEGS_IDLE;
  108.     body->s.torsoAnim = TORSO_STAND;
  109.     if( body->s.weapon == WP_NONE ) {
  110.         body->s.weapon = WP_MACHINEGUN;
  111.     }
  112.     if( body->s.weapon == WP_GAUNTLET) {
  113.         body->s.torsoAnim = TORSO_STAND2;
  114.     }
  115.     body->s.event = 0;
  116.     body->r.svFlags = ent->r.svFlags;
  117.     VectorCopy (ent->r.mins, body->r.mins);
  118.     VectorCopy (ent->r.maxs, body->r.maxs);
  119.     VectorCopy (ent->r.absmin, body->r.absmin);
  120.     VectorCopy (ent->r.absmax, body->r.absmax);
  121.     body->clipmask = CONTENTS_SOLID | CONTENTS_PLAYERCLIP;
  122.     body->r.contents = CONTENTS_BODY;
  123.     body->r.ownerNum = ent->r.ownerNum;
  124.     body->takedamage = qfalse;
  125.  
  126.     VectorSubtract( level.intermission_origin, pad->r.currentOrigin, vec );
  127.     vectoangles( vec, body->s.apos.trBase );
  128.     body->s.apos.trBase[PITCH] = 0;
  129.     body->s.apos.trBase[ROLL] = 0;
  130.  
  131.     AngleVectors( body->s.apos.trBase, f, r, u );
  132.     VectorMA( pad->r.currentOrigin, offset[0], f, vec );
  133.     VectorMA( vec, offset[1], r, vec );
  134.     VectorMA( vec, offset[2], u, vec );
  135.  
  136.     G_SetOrigin( body, vec );
  137.  
  138.     trap_LinkEntity (body);
  139.  
  140.     body->count = place;
  141.  
  142.     return body;
  143. }
  144.  
  145.  
  146. static void CelebrateStop( gentity_t *player ) {
  147.     int        anim;
  148.  
  149.     if( player->s.weapon == WP_GAUNTLET) {
  150.         anim = TORSO_STAND2;
  151.     }
  152.     else {
  153.         anim = TORSO_STAND;
  154.     }
  155.     player->s.torsoAnim = ( ( player->s.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim;
  156. }
  157.  
  158.  
  159. #define    TIMER_GESTURE    (34*66+50)
  160. static void CelebrateStart( gentity_t *player ) {
  161.     player->s.torsoAnim = ( ( player->s.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | TORSO_GESTURE;
  162.     player->nextthink = level.time + TIMER_GESTURE;
  163.     player->think = CelebrateStop;
  164.  
  165.     player->client->ps.events[player->client->ps.eventSequence & (MAX_PS_EVENTS-1)] = EV_TAUNT;
  166.     player->client->ps.eventParms[player->client->ps.eventSequence & (MAX_PS_EVENTS-1)] = 0;
  167.     player->client->ps.eventSequence++;
  168. }
  169.  
  170.  
  171. static vec3_t    offsetFirst  = {0, 0, 74};
  172. static vec3_t    offsetSecond = {-10, 60, 54};
  173. static vec3_t    offsetThird  = {-19, -60, 45};
  174.  
  175. static void PodiumPlacementThink( gentity_t *podium ) {
  176.     vec3_t        vec;
  177.     vec3_t        origin;
  178.     vec3_t        f, r, u;
  179.  
  180.     podium->nextthink = level.time + 100;
  181.  
  182.     AngleVectors( level.intermission_angle, vec, NULL, NULL );
  183.     VectorMA( level.intermission_origin, trap_Cvar_VariableIntegerValue( "g_podiumDist" ), vec, origin );
  184.     origin[2] -= trap_Cvar_VariableIntegerValue( "g_podiumDrop" );
  185.     G_SetOrigin( podium, origin );
  186.  
  187.     if( podium1 ) {
  188.         VectorSubtract( level.intermission_origin, podium->r.currentOrigin, vec );
  189.         vectoangles( vec, podium1->s.apos.trBase );
  190.         podium1->s.apos.trBase[PITCH] = 0;
  191.         podium1->s.apos.trBase[ROLL] = 0;
  192.  
  193.         AngleVectors( podium1->s.apos.trBase, f, r, u );
  194.         VectorMA( podium->r.currentOrigin, offsetFirst[0], f, vec );
  195.         VectorMA( vec, offsetFirst[1], r, vec );
  196.         VectorMA( vec, offsetFirst[2], u, vec );
  197.  
  198.         G_SetOrigin( podium1, vec );
  199.     }
  200.  
  201.     if( podium2 ) {
  202.         VectorSubtract( level.intermission_origin, podium->r.currentOrigin, vec );
  203.         vectoangles( vec, podium2->s.apos.trBase );
  204.         podium2->s.apos.trBase[PITCH] = 0;
  205.         podium2->s.apos.trBase[ROLL] = 0;
  206.  
  207.         AngleVectors( podium2->s.apos.trBase, f, r, u );
  208.         VectorMA( podium->r.currentOrigin, offsetSecond[0], f, vec );
  209.         VectorMA( vec, offsetSecond[1], r, vec );
  210.         VectorMA( vec, offsetSecond[2], u, vec );
  211.  
  212.         G_SetOrigin( podium2, vec );
  213.     }
  214.  
  215.     if( podium3 ) {
  216.         VectorSubtract( level.intermission_origin, podium->r.currentOrigin, vec );
  217.         vectoangles( vec, podium3->s.apos.trBase );
  218.         podium3->s.apos.trBase[PITCH] = 0;
  219.         podium3->s.apos.trBase[ROLL] = 0;
  220.  
  221.         AngleVectors( podium3->s.apos.trBase, f, r, u );
  222.         VectorMA( podium->r.currentOrigin, offsetThird[0], f, vec );
  223.         VectorMA( vec, offsetThird[1], r, vec );
  224.         VectorMA( vec, offsetThird[2], u, vec );
  225.  
  226.         G_SetOrigin( podium3, vec );
  227.     }
  228. }
  229.  
  230.  
  231. static gentity_t *SpawnPodium( void ) {
  232.     gentity_t    *podium;
  233.     vec3_t        vec;
  234.     vec3_t        origin;
  235.  
  236.     podium = G_Spawn();
  237.     if ( !podium ) {
  238.         return NULL;
  239.     }
  240.  
  241.     podium->classname = "podium";
  242.     podium->s.eType = ET_GENERAL;
  243.     podium->s.number = podium - g_entities;
  244.     podium->clipmask = CONTENTS_SOLID;
  245.     podium->r.contents = CONTENTS_SOLID;
  246.     podium->s.modelindex = G_ModelIndex( SP_PODIUM_MODEL );
  247.  
  248.     AngleVectors( level.intermission_angle, vec, NULL, NULL );
  249.     VectorMA( level.intermission_origin, trap_Cvar_VariableIntegerValue( "g_podiumDist" ), vec, origin );
  250.     origin[2] -= trap_Cvar_VariableIntegerValue( "g_podiumDrop" );
  251.     G_SetOrigin( podium, origin );
  252.  
  253.     VectorSubtract( level.intermission_origin, podium->r.currentOrigin, vec );
  254.     podium->s.apos.trBase[YAW] = vectoyaw( vec );
  255.     trap_LinkEntity (podium);
  256.  
  257.     podium->think = PodiumPlacementThink;
  258.     podium->nextthink = level.time + 100;
  259.     return podium;
  260. }
  261.  
  262.  
  263. /*
  264. ==================
  265. SpawnModelsOnVictoryPads
  266. ==================
  267. */
  268. void SpawnModelsOnVictoryPads( void ) {
  269.     gentity_t    *player;
  270.     gentity_t    *podium;
  271.  
  272.     podium1 = NULL;
  273.     podium2 = NULL;
  274.     podium3 = NULL;
  275.  
  276.     podium = SpawnPodium();
  277.  
  278.     player = SpawnModelOnVictoryPad( podium, offsetFirst, &g_entities[level.sortedClients[0]],
  279.                 level.clients[ level.sortedClients[0] ].ps.persistant[PERS_RANK] &~ RANK_TIED_FLAG );
  280.     if ( player ) {
  281.         player->nextthink = level.time + 2000;
  282.         player->think = CelebrateStart;
  283.         podium1 = player;
  284.     }
  285.  
  286.     player = SpawnModelOnVictoryPad( podium, offsetSecond, &g_entities[level.sortedClients[1]],
  287.                 level.clients[ level.sortedClients[1] ].ps.persistant[PERS_RANK] &~ RANK_TIED_FLAG );
  288.     if ( player ) {
  289.         podium2 = player;
  290.     }
  291.  
  292.     if ( level.numNonSpectatorClients > 2 ) {
  293.         player = SpawnModelOnVictoryPad( podium, offsetThird, &g_entities[level.sortedClients[2]],
  294.                 level.clients[ level.sortedClients[2] ].ps.persistant[PERS_RANK] &~ RANK_TIED_FLAG );
  295.         if ( player ) {
  296.             podium3 = player;
  297.         }
  298.     }
  299. }
  300.  
  301.  
  302. /*
  303. ===============
  304. Svcmd_AbortPodium_f
  305. ===============
  306. */
  307. void Svcmd_AbortPodium_f( void ) {
  308.     if( g_gametype.integer != GT_SINGLE_PLAYER ) {
  309.         return;
  310.     }
  311.  
  312.     if( podium1 ) {
  313.         podium1->nextthink = level.time;
  314.         podium1->think = CelebrateStop;
  315.     }
  316. }
  317.